<?php

namespace Aoe\Intent\Request\Http;


class Url
{
    protected ?string $uri = null;
    
    protected ?string $script = null;
    
    protected ?string $domain = null;
    
    /**
     * ## 127.0.0.1/admin/index.php/module/controller/action.html?a=a
     *
     * @return string 请求URI
     * @noinspection PhpUnused
     */
    public function getRequestUri(): string
    {
        if (!$this->uri) {
            if (isset($_SERVER['REQUEST_URI'])) {
                $uri = $_SERVER['REQUEST_URI'];
            } elseif (isset($_SERVER['argv'])) {
                $uri = $_SERVER['PHP_SELF'] . '?' . $_SERVER['argv'][0];
            } else {
                $uri = $_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'];
            }
            $this->uri = $uri;
        }
        return $this->uri;
    }
    
    /**
     * ## /module/controller/action
     *
     * @return string pathinfo
     */
    public function getPathinfo(): string
    {
        return $_SERVER['PATH_INFO'] ?? 'index/index/index';
    }
    
    /**
     * ## www.domain.com:port/$file/$pathinfo
     *
     * @param string      $pathinfo pathinfo
     * @param string|null $file     脚本
     *
     * @return string
     */
    public function makeUrl(string $pathinfo, ?string $file = null): string
    {
        return $this->getDomain() . $this->makeUrlWithoutDomain($pathinfo, $file);
    }

    /**
     * ## /$file/$pathinfo
     *
     * @param string      $pathinfo pathinfo
     * @param string|null $file     脚本
     *
     * @return string
     */
    public function makeUrlWithoutDomain(string $pathinfo, ?string $file = null): string
    {
        $file = empty($file) ? $this->getScriptUrl() : '/' . trim($file, '/');
        return $file . '/' . trim($pathinfo, '/') . '/';
    }
    
    /**
     * ## /admin/index.php
     *
     * @return string 获取请求脚本
     */
    public function getScriptUrl(): string
    {
        if ($this->script === null) {
            $scriptFile = $this->getScriptFile();
            $scriptName = basename($scriptFile);
            if (basename($_SERVER['SCRIPT_NAME']) === $scriptName) {
                $this->script = $_SERVER['SCRIPT_NAME'];
            } elseif (basename($_SERVER['PHP_SELF']) === $scriptName) {
                $this->script = $_SERVER['PHP_SELF'];
            } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $scriptName) {
                $this->script = $_SERVER['ORIG_SCRIPT_NAME'];
            } elseif (($pos = strpos($_SERVER['PHP_SELF'], '/' . $scriptName)) !== false) {
                $this->script = substr($_SERVER['SCRIPT_NAME'], 0, $pos) . 'Url.php/' . $scriptName;
            } elseif (!empty($_SERVER['DOCUMENT_ROOT']) && str_starts_with($scriptFile, $_SERVER['DOCUMENT_ROOT'])) {
                $this->script = str_replace(
                    '\\', '/', str_replace($_SERVER['DOCUMENT_ROOT'], '', $scriptFile),
                );
            } else {
                $this->script = '';
            }
        }
        
        return $this->script;
    }
    
    /**
     * ## real/path/to/admin/index.php
     *
     * @return string 获取请求脚本的真实路径
     */
    public function getScriptFile(): string
    {
        return $_SERVER['SCRIPT_FILENAME'];
    }
    
    /**
     * ## http://127.0.0.1:80
     *
     * @return string domain
     */
    public function getDomain(): string
    {
        if ($this->domain === null)
            $this->domain = $this->getProtocol() . $_SERVER['HTTP_HOST'] . ':' . $_SERVER['SERVER_PORT'];
        return $this->domain;
    }
    
    /**
     * ## http://
     *
     * @return string protocol
     */
    public function getProtocol(): string
    {
        /** @noinspection HttpUrlsUsage */
        return (
            (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
            || $_SERVER['SERVER_PORT'] == 443
        ) ? "https://" : "http://";
    }
}